home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Ebooks / Thinking in C++ V2 / C25 / ObservedFlower.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-25  |  4.4 KB  |  156 lines

  1. //: C25:ObservedFlower.cpp
  2. // From Thinking in C++, 2nd Edition
  3. // Available at http://www.BruceEckel.com
  4. // (c) Bruce Eckel 1999
  5. // Copyright notice in Copyright.txt
  6. // Demonstration of "observer" pattern
  7. #include "Observable.h"
  8. #include <iostream>
  9. #include <vector>
  10. #include <algorithm>
  11. #include <string>
  12. using namespace std;
  13.  
  14. class Flower {
  15.   bool isOpen;
  16. public:
  17.   Flower() : isOpen(false), 
  18.     openNotifier(this), closeNotifier(this) {}
  19.   void open() { // Opens its petals
  20.     isOpen = true;
  21.     openNotifier.notifyObservers();
  22.     closeNotifier.open();
  23.   }
  24.   void close() { // Closes its petals
  25.     isOpen = false;
  26.     closeNotifier.notifyObservers();
  27.     openNotifier.close();
  28.   }
  29.   // Using the "inner class" idiom:
  30.   class OpenNotifier;
  31.   friend class Flower::OpenNotifier;
  32.   class OpenNotifier : public Observable {
  33.     Flower* parent;
  34.     bool alreadyOpen;
  35.   public:
  36.     OpenNotifier(Flower* f) : parent(f), 
  37.       alreadyOpen(false) {}
  38.     void notifyObservers(Argument* arg=0) {
  39.       if(parent->isOpen && !alreadyOpen) {
  40.         setChanged();
  41.         Observable::notifyObservers();
  42.         alreadyOpen = true;
  43.       }
  44.     }
  45.     void close() { alreadyOpen = false; }
  46.   } openNotifier;
  47.   class CloseNotifier;
  48.   friend class Flower::CloseNotifier;
  49.   class CloseNotifier : public Observable {
  50.     Flower* parent;
  51.     bool alreadyClosed;
  52.   public:
  53.     CloseNotifier(Flower* f) : parent(f), 
  54.       alreadyClosed(false) {}
  55.     void notifyObservers(Argument* arg=0) {
  56.       if(!parent->isOpen && !alreadyClosed) {
  57.         setChanged();
  58.         Observable::notifyObservers();
  59.         alreadyClosed = true;
  60.       }
  61.     }
  62.     void open() { alreadyClosed = false; }
  63.   } closeNotifier;
  64. };
  65.  
  66. class Bee {
  67.   string name;
  68.   // An "inner class" for observing openings:
  69.   class OpenObserver;
  70.   friend class Bee::OpenObserver;
  71.   class OpenObserver : public Observer {
  72.     Bee* parent;
  73.   public:
  74.     OpenObserver(Bee* b) : parent(b) {}
  75.     void update(Observable*, Argument *) {
  76.       cout << "Bee " << parent->name 
  77.         << "'s breakfast time!\n";
  78.     }
  79.   } openObsrv;
  80.   // Another "inner class" for closings:
  81.   class CloseObserver;
  82.   friend class Bee::CloseObserver;
  83.   class CloseObserver : public Observer {
  84.     Bee* parent;
  85.   public:
  86.     CloseObserver(Bee* b) : parent(b) {}
  87.     void update(Observable*, Argument *) {
  88.       cout << "Bee " << parent->name 
  89.         << "'s bed time!\n";
  90.     }
  91.   } closeObsrv;
  92. public:
  93.   Bee(string nm) : name(nm), 
  94.     openObsrv(this), closeObsrv(this) {}
  95.   Observer& openObserver() { return openObsrv; }
  96.   Observer& closeObserver() { return closeObsrv;}
  97. };
  98.  
  99. class Hummingbird {
  100.   string name;
  101.   class OpenObserver;
  102.   friend class Hummingbird::OpenObserver;
  103.   class OpenObserver : public Observer {
  104.     Hummingbird* parent;
  105.   public:
  106.     OpenObserver(Hummingbird* h) : parent(h) {}
  107.     void update(Observable*, Argument *) {
  108.       cout << "Hummingbird " << parent->name 
  109.         << "'s breakfast time!\n";
  110.     }
  111.   } openObsrv;
  112.   class CloseObserver;
  113.   friend class Hummingbird::CloseObserver;
  114.   class CloseObserver : public Observer {
  115.     Hummingbird* parent;
  116.   public:
  117.     CloseObserver(Hummingbird* h) : parent(h) {}
  118.     void update(Observable*, Argument *) {
  119.       cout << "Hummingbird " << parent->name 
  120.         << "'s bed time!\n";
  121.     }
  122.   } closeObsrv;
  123. public:
  124.   Hummingbird(string nm) : name(nm), 
  125.     openObsrv(this), closeObsrv(this) {}
  126.   Observer& openObserver() { return openObsrv; }
  127.   Observer& closeObserver() { return closeObsrv;}
  128. };
  129.  
  130. int main() {
  131.   Flower f;
  132.   Bee ba("A"), bb("B");
  133.   Hummingbird ha("A"), hb("B");
  134.   f.openNotifier.addObserver(ha.openObserver());
  135.   f.openNotifier.addObserver(hb.openObserver());
  136.   f.openNotifier.addObserver(ba.openObserver());
  137.   f.openNotifier.addObserver(bb.openObserver());
  138.   f.closeNotifier.addObserver(ha.closeObserver());
  139.   f.closeNotifier.addObserver(hb.closeObserver());
  140.   f.closeNotifier.addObserver(ba.closeObserver());
  141.   f.closeNotifier.addObserver(bb.closeObserver());
  142.   // Hummingbird B decides to sleep in:
  143.   f.openNotifier.deleteObserver(hb.openObserver());
  144.   // Something changes that interests observers:
  145.   f.open();
  146.   f.open(); // It's already open, no change.
  147.   // Bee A doesn't want to go to bed:
  148.   f.closeNotifier.deleteObserver(
  149.     ba.closeObserver());
  150.   f.close();
  151.   f.close(); // It's already closed; no change
  152.   f.openNotifier.deleteObservers();
  153.   f.open();
  154.   f.close();
  155. } ///:~
  156.